function isObject(value) {
  const valueType = typeof value;
  return (
    valueType !== null && (valueType === "object" || valueType === "function")
  );
}

function deepClone(originValue, map = new WeakMap()) {
  // 判断是否是一个set类型
  if (originValue instanceof Set) {
    return new Set([...originValue]);
  }
  // 判断是否是一个map类型
  if (originValue instanceof Map) {
    return new Map([...originValue]);
  }

  // 是否为symbol
  if (typeof originValue === "symbol") {
    return Symbol(originValue.description);
  }
  // 是否为函数
  if (typeof originValue === "function") {
    return originValue;
  }
  // 是否为对象类型
  if (!isObject(originValue)) {
    return originValue;
  }

  // 查自己
  if (map.has(originValue)) {
    return map.get(originValue);
  }

  // 判断传入的对象是数组还是对象
  const newObject = Array.isArray(originValue) ? [] : {};
  map.set(originValue, newObject);
  for (const key in originValue) {
    newObject[key] = deepClone(originValue[key], map);
  }
  // 对Symbol的key进行特殊的处理
  const symbolKeys = Object.getOwnPropertySymbols(originValue);
  for (const sKey of symbolKeys) {
    newObject[sKey] = deepClone(originValue[sKey], map);
  }
  return newObject;
}

let s1 = Symbol("aaa");
let s2 = Symbol("bbb");
const obj = {
  name: "yz",
  age: 18,
  friend: {
    name: "james",
    address: {
      city: "北京",
    },
  },
  // 数组类型
  hobbies: ["abc", "def", "hij"],
  // 函数类型
  foo: function () {
    console.log("foo function");
  },
  [s1]: "abc",
  s2: s2,
  // Set/Map
  set: new Set(["aaa", "bbb", "ccc"]),
  map: new Map([
    ["bc", "aa"],
    ["bbb", "cba"],
  ]),
};
obj.info = obj;
const newObj = deepClone(obj);
console.log(newObj === obj);

obj.friend.name = "jaja";
console.log("obj");
console.log(obj);
console.log("newObj");
console.log(newObj);
console.log(obj.info.info.info.info.info.info);
